package com.xc.stock.application;

import com.ag.exception.EntityNotFoundException;
import com.ag.exception.SysTipsException;
import com.ag.utils.AgAssert;
import com.ag.utils.NumberUtils;
import com.xc.dao.UserMapper;
import com.xc.pojo.User;
import com.xc.stock.constant.AccountType;
import com.xc.stock.constant.Currency;
import com.xc.stock.domain.basic.entity.Account;
import com.xc.stock.domain.basic.entity.TradeAcc;
import com.xc.stock.domain.basic.service.AccountService;
import com.xc.stock.domain.basic.service.TradeAccService;
import com.xc.stock.dto.model.AccountSelector;
import com.xc.stock.utils.Beans;
import com.xc.stock.utils.SpringUtils;
import com.xc.stock.utils.Utils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TradeAccProcessor {
	TradeAcc tradeAcc;
	Integer accId;
	User user;
	AccountType accountType;
	
	public TradeAcc tradeAcc() {
		if(tradeAcc != null) {
			return tradeAcc;
		}
		if(NumberUtils.isValid(accId)) {
			TradeAcc tradeAcc = TradeAccService.of().repository().find(accId);
			AgAssert.notNull(tradeAcc, EntityNotFoundException.class, "找不到交易账户信息");
			this.tradeAcc = tradeAcc;
			
			UserMapper userMapper = SpringUtils.getBean(UserMapper.class);
			this.user = userMapper.findById(tradeAcc.getDestId());
		} else if(user != null && accountType != null) {
			TradeAcc tradeAcc = checkIfAuth();
			AgAssert.notNull(tradeAcc, EntityNotFoundException.class, "请先开户");
			this.tradeAcc = tradeAcc;
		} else {
			throw new SysTipsException("参数错误~~~");
		}
		
		return tradeAcc;
	}
	
	public TradeAcc checkIfAuth() {
		TradeAcc tradeAcc = TradeAccService.of().getTradeAcc(Utils.userDestInfo(user), accountType);
		if(tradeAcc != null) {
			return tradeAcc;
		}
		
		final TradeAcc tradeAcc2 = new TradeAcc();
		Utils.t().exec(status -> {
			TradeAcc initAcc = initAcc();
			Beans.copyPropertiesIgnoreNull(initAcc, tradeAcc2);
		});
		
		return tradeAcc2;
	}
	
//	public TradeAccInfo info(Currency viewCurrency) {
//		TradeAcc tradeAcc = tradeAcc();
//		List<Account> accountList = AccountRepository.of().findByPkId(tradeAcc.getId());
//		List<StockPosition> positionList = StockPositionRepository.of().findValidByTradeAccId(tradeAcc.getId());
//		ExchangeRate exchangerRate = CApis.of().exchangeRate(viewCurrency);
//		Map<String, StockInfo> stockInfoMap = CommonApis.of().stockDetailMap(Lists.transform(positionList, val -> val.stockCode()));
//		
//		return TradeAccInfo.from(user, tradeAcc, accountList, positionList, viewCurrency, exchangerRate, stockInfoMap);
//	}
	
	public TradeAcc initAcc() {
		TradeAcc acc =  TradeAccService.of().createTradeAcc(Utils.userDestInfo(user), accountType);
		AccountSelector a = AccountSelector.builder()
				.accountType(accountType)
				.currency(Currency.CNY)
				.dest(Utils.userDestInfo(user))
				.pId(acc.getId())
				.build();
		
		AccountService.of().createAccount(a, acc, user.getUserAmt());
		return acc;
	}
	
	public Account findAccount() {
		return findAccount(Currency.CNY);
	}
	
	public Account findAccount(Currency currency) {
		TradeAcc stockAcc = tradeAcc();
		AccountSelector selector = AccountSelector.builder()
				.accountType(AccountType.of(stockAcc.getType()))
				.currency(currency)
				.dest(stockAcc.destInfo())
				.pId(stockAcc.getId())
				.build();
			
		Account account = AccountService.of().getAccount(selector);
		if(account == null) {
			throw new SysTipsException(String.format("找不到[%s]的币种[%s]的账本信息", stockAcc.getId(), currency.remark()));
		}
		
		return account;
	}
	
//	public ExchangeInfoDTO currencyExchangeInfo(User user, Currency from, Currency to) {
//		Account fromAccount = findAccount(from);
//		ExchangeRate exchangerRate = CApis.of().exchangeRate(from);
//		
//		return ExchangeInfoDTO.builder()
//				.from(from)
//				.fromBalance(fromAccount.getBalance())
//				.rate(exchangerRate.toCurrency(from, to))
//				.to(to)
//				.build();
//	}
	
//	/**
//	 * 货币兑换
//	 * @param user
//	 * @param targetAccountNo
//	 * @param money
//	 */
//	@Transactional
//	public void currencyExchange(User user, Currency from, Currency to, BigDecimal fromMoney, String payPwd) {
//		if(BigDecimals.loeZero(fromMoney)) {
//			throw new SysTipsException("兑换金额非法");
//		}
//		
//		if(StringUtils.isNotBlank(payPwd)) {
//			AgAssert.isTrue(user.verifyPayPwd(payPwd), SysTipsException.class, "支付密码不正确");
//		}
//		String exchangeNo = "TFO" + DateUtils.nowDate("yyyyMMddHHmmssS") + NumberUtils.random(6);
//		
//		Account fromAccount = findAccount(from);
//		boolean canBalanceSubtract = fromAccount.canBalanceSubtract(fromMoney);
//		AgAssert.isTrue(canBalanceSubtract, SysTipsException.class, from.remark() + "账户余额不足");
//		
//		Account toAccount = findAccount(to);
//		
//		ExchangeRate exchangerRate = CApis.of().exchangeRate(from);
//		BigDecimal toMoney = exchangerRate.toCurrencyValue(from, to, fromMoney);
//		
//		AccountOperParam op = AccountOperParam.builder()
//				.accountAction(AccountActionEnum.TRANSFER_OUT)
//				.allowNegative(false)
//				.outerNo(exchangeNo)
//				.outerUid(String.valueOf(fromAccount.getId()))
//				.logContent(AccountActionEnum.TRANSFER_OUT.remark())
//				.logExt(new JSONObject())
//				.build();
//		AccountService.of().subtract(fromAccount.getAccountNo(), fromMoney, op);
//
//		TradeSetting setting = Trades.of(Utils.toSource(from)).tradeSetting();
//		
//		BigDecimal tax = BigDecimals.multiplys(toMoney, setting.getExchange()).setScale(2, RoundingMode.HALF_UP);
//		
//		op = AccountOperParam.builder()
//				.accountAction(AccountActionEnum.TRANSFER_IN)
//				.allowNegative(true)
//				.outerNo(exchangeNo)
//				.outerUid(String.valueOf(toAccount.getId()))
//				.logContent(AccountActionEnum.TRANSFER_IN.remark())
//				.logExt(new JSONObject())
//				.build();
//		AccountService.of().add(toAccount.getAccountNo(), BigDecimals.subtract(toMoney, tax), op);
//		
//		CurrencyExchangeCreateCommand currencyExchangeCreateCommand = CurrencyExchangeCreateCommand.builder()
//				.destId(user.getId())
//				.role(RoleEnum.USER.code())
//				.exchangeNo(exchangeNo)
//				.fromCurrency(from.code())
//				.fromMoney(fromMoney)
//				.status(SysConstant.STATUS_NORMAL)
//				.tax(tax)
//				.toCurrency(to.code())
//				.toMoney(toMoney)
//				.build();
//		
//		CurrencyExchangeService.of().create(currencyExchangeCreateCommand);
//		log.info("货币兑换: {}", JSON.toJSONString(currencyExchangeCreateCommand));
//	}
	
	public static TradeAccProcessor of() {
		return new TradeAccProcessor();
	}
	
	public static TradeAccProcessor of(Integer accId) {
		TradeAccProcessor processor = new TradeAccProcessor();
		processor.accId = accId;
		return processor;
	}
	
	public static TradeAccProcessor ofStock(User user) {
		return of(user, AccountType.STOCK);
	}
	
	public static TradeAccProcessor of(User user, AccountType accountType) {
		TradeAccProcessor processor = new TradeAccProcessor();
		processor.user = user;
		processor.accountType  = accountType;
		return processor;
	}
}
